package com.hbnu.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbnu.system.config.BaseException;
import com.hbnu.system.mapper.ZCzxfundsMapper;
import com.hbnu.system.model.entity.Porproject_registration;
import com.hbnu.system.model.entity.ZCzxfunds;
import com.hbnu.system.service.IPorproject_registrationService;
import com.hbnu.system.service.IUserService;
import com.hbnu.system.service.ZCzxfundsService;
import com.hbnu.system.utils.CheckRoleUtil;
import com.hbnu.system.utils.RegexPatterns;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Service
public class ZCzxfundsServiceImpl extends ServiceImpl<ZCzxfundsMapper, ZCzxfunds> implements ZCzxfundsService {
    @Autowired
    ZCzxfundsService zCzxfundsService;  // 修正注入的Service为当前实体的Service
    @Autowired
    IPorproject_registrationService iPorproject_registrationService;
    @Autowired
    private IUserService iUserService;
    @Autowired
    private CheckRoleUtil checkRoleUtil;

    @Override
    public boolean addZCzxfundsProject(ZCzxfunds zcfunds) {
        // 不使用前端传过来的id
        zcfunds.setZcfundsID(null);

        // 查询纵向项目并校验权限（先校验项目ID存在性，再查项目信息）
        if(StrUtil.isEmpty(zcfunds.getPregistrationID()) || StrUtil.isBlank(zcfunds.getPregistrationID())){
            throw new BaseException("请输入纵向项目id!");
        }
        Porproject_registration tr = iPorproject_registrationService.getOne(Wrappers.lambdaQuery(Porproject_registration.class)
                .eq(Porproject_registration::getPRegistrationID, zcfunds.getPregistrationID()));
        if(Objects.isNull(tr)){
            throw new BaseException("纵向项目不存在!");
        }
        checkRoleUtil.checkPermissionProject(tr.getProjectState());  // 移至项目存在性校验后

        // 支出编号校验
        if(StrUtil.isEmpty(zcfunds.getZcfundsNum()) || StrUtil.isBlank(zcfunds.getZcfundsNum())){
            throw new BaseException("请输入支出编号!");
        }
        ZCzxfunds existFunds = zCzxfundsService.getOne(Wrappers.lambdaQuery(ZCzxfunds.class)  // 修正为查询当前实体
                .eq(ZCzxfunds::getZcfundsNum, zcfunds.getZcfundsNum()));
        if(!Objects.isNull(existFunds)){
            throw new BaseException("支出编号已被使用");
        }

        // 支出类别校验
        if(StrUtil.isEmpty(zcfunds.getZcfundsType()) || StrUtil.isBlank(zcfunds.getZcfundsType())){
            throw new BaseException("请输入支出类别!");
        }

        // 支出金额校验（增加数字格式校验）
        if(StrUtil.isEmpty(zcfunds.getZcfundsAmount()) || StrUtil.isBlank(zcfunds.getZcfundsAmount())){
            throw new BaseException("请输入支出金额!");
        }
        if (!zcfunds.getZcfundsAmount().matches(RegexPatterns.NUMBER_REGEX)) {  // 与到账逻辑保持一致
            throw new BaseException("支出金额请输入数字");
        }

        // 支出时间校验（修正提示文本）
        if(Objects.isNull(zcfunds.getZcfundsDate())){
            throw new BaseException("请输入支出时间!");
        }

        // 更新项目总支出金额
        float assessment = Float.parseFloat(zcfunds.getZcfundsAmount());
        float num = tr.getZcFunds() + assessment;
        tr.setZcFunds(num);
        UpdateWrapper<Porproject_registration> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("PRegistrationID", tr.getPRegistrationID());
        iPorproject_registrationService.update(tr, updateWrapper);

        // 设置上传时间并保存
        zcfunds.setUploadTime(LocalDateTime.now());
        return baseMapper.insert(zcfunds) == 1;
    }

    @Override
    public boolean updateZCzxfundsProject(ZCzxfunds zcfunds) {
        // 项目ID校验
        if(StrUtil.isEmpty(zcfunds.getPregistrationID()) || StrUtil.isBlank(zcfunds.getPregistrationID())){
            throw new BaseException("请输入纵向项目id!");
        }

        // 项目存在性校验
        Porproject_registration tr = iPorproject_registrationService.getOne(Wrappers.lambdaQuery(Porproject_registration.class)
                .eq(Porproject_registration::getPRegistrationID, zcfunds.getPregistrationID()));
        if(Objects.isNull(tr)){
            throw new BaseException("纵向项目不存在!");
        }

        // 权限校验
        checkRoleUtil.checkPermissionProject(tr.getProjectState());

        // 支出编号校验（排除当前记录）
        if(StrUtil.isEmpty(zcfunds.getZcfundsNum()) || StrUtil.isBlank(zcfunds.getZcfundsNum())){
            throw new BaseException("请输入支出编号!");
        }
        ZCzxfunds existFunds = zCzxfundsService.getOne(Wrappers.lambdaQuery(ZCzxfunds.class)  // 修正为查询当前实体
                .eq(ZCzxfunds::getZcfundsNum, zcfunds.getZcfundsNum())
                .ne(ZCzxfunds::getZcfundsID, zcfunds.getZcfundsID()));
        if(!Objects.isNull(existFunds)){
            throw new BaseException("支出编号已被使用");
        }

        // 支出类别校验
        if(StrUtil.isEmpty(zcfunds.getZcfundsType()) || StrUtil.isBlank(zcfunds.getZcfundsType())){
            throw new BaseException("请输入支出类别!");
        }

        // 支出金额校验（增加数字格式校验）
        if(StrUtil.isEmpty(zcfunds.getZcfundsAmount()) || StrUtil.isBlank(zcfunds.getZcfundsAmount())){
            throw new BaseException("请输入支出金额!");
        }
        if (!zcfunds.getZcfundsAmount().matches(RegexPatterns.NUMBER_REGEX)) {  // 与到账逻辑保持一致
            throw new BaseException("支出金额请输入数字");
        }

        // 支出时间校验（修正提示文本）
        if(Objects.isNull(zcfunds.getZcfundsDate())){
            throw new BaseException("请输入支出时间!");
        }

        // 查询原记录（修正为查询当前实体的记录）
        ZCzxfunds oldFunds = zCzxfundsService.getOne(Wrappers.lambdaQuery(ZCzxfunds.class)
                .eq(ZCzxfunds::getZcfundsID, zcfunds.getZcfundsID()));
        if(Objects.isNull(oldFunds)){
            throw new BaseException("该支出记录不存在!");
        }

        // 计算金额差值并更新项目总支出
        float oldAmount = Float.parseFloat(oldFunds.getZcfundsAmount());
        float newAmount = Float.parseFloat(zcfunds.getZcfundsAmount());
        float num = tr.getZcFunds() + (newAmount - oldAmount);
        tr.setZcFunds(num);
        UpdateWrapper<Porproject_registration> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("PRegistrationID", tr.getPRegistrationID());
        iPorproject_registrationService.update(tr, updateWrapper);

        // 更新上传时间并保存
        zcfunds.setUploadTime(LocalDateTime.now());
        return baseMapper.updateById(zcfunds) == 1;
    }

    @Override
    public boolean removeZCzxfundsProject(String zcfundsID) {
        // 查询待删除记录
        ZCzxfunds zcfunds = zCzxfundsService.getOne(Wrappers.lambdaQuery(ZCzxfunds.class)  // 使用当前Service查询
                .eq(ZCzxfunds::getZcfundsID, zcfundsID));
        if(Objects.isNull(zcfunds)){
            throw new BaseException("不存在该支出经费");
        }

        // 校验关联项目
        Porproject_registration tr = iPorproject_registrationService.getOne(Wrappers.lambdaQuery(Porproject_registration.class)
                .eq(Porproject_registration::getPRegistrationID, zcfunds.getPregistrationID()));
        if(Objects.isNull(tr)){
            throw new BaseException("纵向项目不存在!");
        }

        // 权限校验
        checkRoleUtil.checkPermissionProject(tr.getProjectState());

        // 从项目总支出中减去当前金额
        float removeAmount = Float.parseFloat(zcfunds.getZcfundsAmount());
        float num = tr.getZcFunds() - removeAmount;
        tr.setZcFunds(num);
        UpdateWrapper<Porproject_registration> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("PRegistrationID", tr.getPRegistrationID());
        iPorproject_registrationService.update(tr, updateWrapper);

        // 删除记录
        return baseMapper.deleteById(zcfunds) == 1;
    }

    @Override
    public List<ZCzxfunds> getZCzxfundsByPorprojectID(String porprojectID) {  // 统一参数命名
        // 校验项目存在性
        Porproject_registration project = iPorproject_registrationService.getById(porprojectID);
        if(Objects.isNull(project)){
            throw new BaseException("输入的纵向项目编号有误");
        }

        // 查询项目下的所有支出记录
        List<ZCzxfunds> zcfundsList = baseMapper.selectList(Wrappers.lambdaQuery(ZCzxfunds.class)
                .eq(ZCzxfunds::getPregistrationID, porprojectID));
        return zcfundsList;
    }
}
